package com.example.springboot;

import org.apache.catalina.Context;
import org.apache.catalina.Engine;
import org.apache.catalina.core.StandardHost;
import org.apache.catalina.ha.session.BackupManager;
import org.apache.catalina.ha.session.ClusterSessionListener;
import org.apache.catalina.ha.session.DeltaManager;
import org.apache.catalina.ha.tcp.SimpleTcpCluster;
import org.apache.catalina.tribes.group.GroupChannel;
import org.apache.catalina.tribes.group.interceptors.MessageDispatchInterceptor;
import org.apache.catalina.tribes.group.interceptors.TcpFailureDetector;
import org.apache.catalina.tribes.membership.McastService;
import org.apache.catalina.tribes.tipis.AbstractReplicatedMap;
import org.apache.catalina.tribes.tipis.ReplicatedMap;
import org.apache.catalina.tribes.transport.ReplicationTransmitter;
import org.apache.catalina.tribes.transport.nio.NioReceiver;
import org.apache.catalina.tribes.transport.nio.PooledParallelSender;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.ClassUtils;

import javax.servlet.ServletContextAttributeEvent;
import javax.servlet.ServletContextAttributeListener;

@Component
public class MyTomcatServletWebServerFactory extends TomcatServletWebServerFactory implements ServletContextAttributeListener {
    @Autowired
    MyMapValue myMapValue;

    @Override
    protected void postProcessContext(Context context) {
        StandardHost host = (StandardHost) context.getParent();
        Engine parent = (Engine) host.getParent();
        SimpleTcpCluster tcpCluster = new SimpleTcpCluster();
        tcpCluster.setChannelSendOptions(67);
        BackupManager backupManager=new BackupManager();
        backupManager.setMapSendOptions(6);
        backupManager.setContext(context);
        tcpCluster.registerManager(backupManager);
        DeltaManager deltaManager=new DeltaManager();
        deltaManager.setNotifySessionListenersOnReplication(true);
        deltaManager.setExpireSessionsOnShutdown(true);
        deltaManager.setContext(context);
        tcpCluster.registerManager(deltaManager);
        context.setManager(deltaManager);
        GroupChannel groupChannel=new GroupChannel();
        McastService mcastService=new McastService();
        mcastService.setAddress("228.0.0.4");
        mcastService.setPort(45564);
        mcastService.setFrequency(500);
        mcastService.setDropTime(3000);
        groupChannel.setMembershipService(mcastService);
        NioReceiver nioReceiver=new NioReceiver();
        nioReceiver.setAddress("auto");
        nioReceiver.setPort(4000);
        nioReceiver.setAutoBind(100);
        nioReceiver.setSelectorTimeout(5000);
        nioReceiver.setMaxThreads(10);
        groupChannel.setChannelReceiver(nioReceiver);
        ReplicationTransmitter channelSender=new ReplicationTransmitter();
        PooledParallelSender pooledParallelSender=new PooledParallelSender();
        channelSender.setTransport(pooledParallelSender);
        groupChannel.addInterceptor(new TcpFailureDetector());
        groupChannel.addInterceptor(new MessageDispatchInterceptor());
        groupChannel.addChannelListener(new MapClusterListener());
        groupChannel.setChannelSender(channelSender);
        tcpCluster.setChannel(groupChannel);
        parent.setCluster(tcpCluster);
        myMapValue.setCluster(tcpCluster);
    }
}
